import random
import struct
import hashlib


class TlvBuilder(object):
    def __init__(self, data={}):
        self.fmt_head = "BBBBHHBBBBHBB"
        self.tlv_ver = data.get("ver", 1)
        self.tlv_type = data.get("type", 0)
        self.tlv_pap_chap = data.get("pap_chap", 1)
        self.tlv_rsvd = data.get("rsvd", 0)
        self.tlv_serial_no = data.get("serial_no", 0)
        self.tlv_req_id = data.get("req_id", 0)
        self.tlv_user_ip = data.get("user_ip", "0.0.0.0")
        self.tlv_user_port = data.get("user_port", 0)
        self.tlv_err_code = data.get("err_code", 0)
        self.tlv_attr = data.get("attr", {})
        self.tlv_user_ip_arr = self.__ip_parser()
        self.tlv_attr_num = len(self.tlv_attr)
        self.value_list_head = self.__create_value_list_head()

    def change_attr(self, data={}):
        self.tlv_ver = data.get("ver", self.tlv_ver)
        self.tlv_type = data.get("type", self.tlv_type)
        self.tlv_pap_chap = data.get("pap_chap", self.tlv_pap_chap)
        self.tlv_rsvd = data.get("rsvd", self.tlv_rsvd)
        self.tlv_serial_no = data.get("serial_no", self.tlv_serial_no)
        self.tlv_req_id = data.get("req_id", self.tlv_req_id)
        self.tlv_user_ip = data.get("user_ip", self.tlv_user_ip)
        self.tlv_user_port = data.get("user_port", self.tlv_user_port)
        self.tlv_err_code = data.get("err_code", self.tlv_err_code)
        self.tlv_attr = data.get("attr", self.tlv_attr)
        self.tlv_user_ip_arr = self.__ip_parser()
        self.tlv_attr_num = len(self.tlv_attr)
        self.value_list_head = self.__create_value_list_head()

    def __ip_parser(self):
        result = [0, 0, 0, 0]
        if self.tlv_user_ip.split is not None and self.tlv_user_ip.split != "":
            result = self.tlv_user_ip.split('.')
        return result

    def print_attr(self):
        print_str = "ver:%s\ntype:%s\npap_chap:%s\nrsvd:%s\nserial_no:%s\nreq_id:%s\nuser_ip:%s\nuser_port:%s\nerr_code:%s\nattr:%s\n"
        print(print_str % (
            self.tlv_ver, self.tlv_type, self.tlv_pap_chap, self.tlv_rsvd, self.tlv_serial_no, self.tlv_req_id,
            self.tlv_user_ip, self.tlv_user_port, self.tlv_err_code, self.tlv_attr))

    def tlv_result_parser(self, data):
        print(data)
        result = False
        if data[14] == 0 or data[14] == 2:
            result = True
        print(result)
        return result

    def get_online_data(self):
        self.tlv_type = 3
        return self.build_data()

    def get_offline_data(self):
        self.tlv_type = 5
        return self.build_data()

    def build_data(self):
        result = self.__create_data()
        return result

    def __create_data(self):
        fmt = self.__create_data_fmt()
        data = self.__create_data_value_list()
        result = struct.pack(fmt, *data)
        return result

    def __create_data_fmt(self):
        data_fmt = self.fmt_head
        for i in self.tlv_attr:
            if i == "abmac":
                data_fmt += "BB%ss" % str(len(bytes.fromhex(self.tlv_attr[i])))
            else:
                data_fmt += "BB%ss" % str(len(self.tlv_attr[i].encode("utf-8")))
        return data_fmt

    def __create_data_value_list(self):
        data_value_list = self.__create_value_list_head()
        for i in self.tlv_attr:
            if i == "username":
                data_value_list.append(1)
            elif i == "password":
                data_value_list.append(2)
            elif i == "challenge":
                data_value_list.append(3)
            elif i == "chappassword":
                data_value_list.append(4)
            elif i == "challenge":
                data_value_list.append(3)
            elif i == "chappassword":
                data_value_list.append(4)
            elif i == "abmac":
                data_value_list.append(238)
            elif i == "abchekone":
                data_value_list.append(240)
            elif i == "abchektwo":
                data_value_list.append(241)
            if i == "abmac":
                data_value_list.append(len(bytes.fromhex(self.tlv_attr[i])) + 2)
                data_value_list.append(bytes.fromhex(self.tlv_attr[i]))
            else:
                data_value_list.append(len(self.tlv_attr[i].encode("utf-8")) + 2)
                data_value_list.append(self.tlv_attr[i].encode("utf-8"))
        return data_value_list

    def __create_value_list_head(self):
        value_list = []
        value_list.append(self.tlv_ver)
        value_list.append(self.tlv_type)
        value_list.append(self.tlv_pap_chap)
        value_list.append(self.tlv_rsvd)
        value_list.append(self.tlv_serial_no)
        value_list.append(self.tlv_req_id)
        for i in self.tlv_user_ip_arr:
            value_list.append(int(i))
        value_list.append(self.tlv_user_port)
        value_list.append(self.tlv_err_code)
        value_list.append(self.tlv_attr_num)
        return value_list


if __name__ == "__main__":
    data = {"type": 3, "serial_no": 22080, "user_ip": "192.168.1.190",
            "attr": {"username": "zyt", "password": "123456"}, "secret": "123456789"}
    tb = TlvBuilder(data)
    print(tb.build_data())
